/**
 * @file HaierU+Uart.h
 * @brief
 * @author xuesong (wenshaoliu@foxmail.com)
 * @version 1.0
 * @date 2024-08-17
 *
 * @copyright Copyright (c) 2024  by xuesong
 *
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2024-08-17     <td>1.0     <td>xuesong   <td>内容
 * </table>
 */
#ifndef __HAIERU_UART__H__
#define __HAIERU_UART__H__

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdint.h>
#include "LoopFIFO.h"
#include "streambuffer.h"
    //-------------------------------------------------------
    typedef enum
    {
        D_CTRL = 1,                //  控制                 模块<->设备     主从/交互      必选
        D_STATUS,                  //  状态                 模块<->设备     主从/交互      必选
        D_NULL03,                  //  无效                 模块<->设备     主从/交互      必选
        D_ALARM_STATUS,            //  报警状态汇报          模块<->设备     交互          必选
        D_CONFIRM,                 //  确认                 模块<->设备     主从/交互      必选
        D_REPORT,                  //  汇报                 模块<->设备     交互           必选
        D_StopAlarm = 9,           //  停止故障报警          模块->设备      交互           必选
        D_SysDown = 0x11,          //  系统下行              模块->设备      主从/交互      可选
        D_DeviceUp,                //  设备上行              模块<-设备      交互           可选
        D_SysAsk,                  //  系统查询              模块->设备      主从/交互       可选
        D_DeviceAckSysAsk,         //  系统查询应答          模块<-设备      主从/交互       可选
        D_DeviceAsk,               //  设备查询              模块<-设备      主从/交互       可选
        D_SysAckDeviceAsk,         //  设备查询应答          模块->设备      主从/交互       可选
        D_GROUP_CMD = 0x60,        //  组命令                模块->设备      交互           可选
        D_AskDeviceVer,            //  查询设备版本          模块->设备      主从/交互       必选
        D_DeviceAckVer,            //  设备应答版本          模块<-设备      主从/交互       必选
        D_AskAllSlaveAddr = 0x67,  //  查询全部子机地址      模块->设备      交互            可选
        D_AckAllSlaveAddr,         //  回复全部子机地址      模块<-设备      交互            可选
        D_SlaveChangeNotify,       //  子机变化通知          模块<-设备      交互            可选
        D_AskDeviceId = 0x70,      //  查询设备识别码        模块->设备      主从/交互       必选
        D_AckDeviceId,             //  应答设备识别码        模块<-设备      主从/交互       必选
        D_AskAlarmStatus = 0x73,   //  查询报警状态          模块->设备      主从/交互       必选
        D_AckAlarmStatus,          //  应答报警状态          模块<-设备      主从/交互       必选
        D_SetDeviceConfig = 0x7C,  //  设备汇报配置          模块->设备      交互            必选
        D_AckDeviceConfig,         //  设备汇报配置应答      模块<-设备      交互            必选
        D_SendDeviceOTA = 0xE1,    //  下发设备OTA指令      模块->设备      主从/交互       OTA必选
        D_AckDeviceOTA,            //  下发设备OTA应答      模块<-设备      主从/交互       OTA必选
        D_GetDeviceDFU = 0xE5,     //  获取整机固件         模块<-设备      主从/交互       OTA必选
        D_AckDeviceDFU,            //  获取整机固件应答     模块->设备      主从/交互       OTA必选
        D_SetUartBaud,             //  切换波特率           模块<-设备      主从/交互       OTA必选
        D_SetUartBaudAck,          //  切换波特率应答       模块->设备      主从/交互       OTA必选
        D_AskSBordInfo,            //  查询子板信息         模块->设备      主从/交互       必选
        D_AckSBordInfo,            //  查询子板信息应答     模块<-设备      主从/交互       必选
        D_ReportOtaResult,         //  整机升级结果上报     模块<-设备      主从/交互       OTA必选
        D_OtaResultAck = 0xEF,     //  升级结果上报应答     模块->设备      主从/交互       OTA必选
        D_NetStatusAsk = 0xF0,     //  网络状态查询         模块<-设备      交互            可选
        D_NetStatusAck,            //  网络状态应答         模块->设备      交互            可选
        D_WifiIntoSet,             //  wifi进入设置模式     模块<-设备      交互            必选
        D_WifiIntoSetAck,          //  wifi进入设置应答     模块->设备      交互            必选
        D_WifiIntoWork,            //  wifi进入工作         模块<-设备      交互            必选
        D_WifiIntoWorkAck,         //  wifi进入工作应答     模块->设备      交互            必选
        D_ReportNetStatus = 0xF7,  //  汇报网络状态         模块->设备      主从/交互       必选
        D_ClrModeConfig,           //  模块清除配置信息     模块<-设备      交互            可选
        D_DataReportConfig = 0xFA, //  大数据汇报配置       模块->设备      交互            可选
        D_DataReportConfigAck,     //  大数据汇报配置应答   模块<-设备      交互            可选
        D_AskManageInfo,           //  查询管理信息         模块->设备      主从            必选
        D_AskManageInfoAck,        //  查询管理信息应答     模块->设备      主从            必选
        D_ModeWeakUp,              //  唤醒                模块<->设备     主从/交互       可选
    } FLEAM_TYPE;
    //-------------------------------------------------------
    typedef enum
    {
        D_USER_INFO = 0x4D01,        // 查询用户数据信息
        D_BigDATA_INFO = 0x4DFE,     // 查询大数据信息
        D_SingleDATA_INFO = 0x5DFF,  // 设置单个参数：0x5Dxx 设置设备的某个参数，设备返回全部的用户数据信息。数据信息：数据参数
        D_SetZuConfig_INFO = 0x60FF, // 设置组参数：60xx，向设备设置组参数，设备返回全部的用户数据信息,此命令只在主从模式下可用
    } D_CTRL_SubCmd;
    typedef enum
    {
        D_S_USER_INFO = 0x6D01,    // 用户数据信息：6D01。当设备收到查询用户数据信息命令(4D01)、设置单个参数命令(5Dxx)或设置组参数命令(60xx)时，返回此命令。
        D_S_BigDATA_INFO = 0x7D01, // 大数据信息：7D01。当设备收到查询大数据信息命令(4DFE)时，返回此命令。此命令只在主从模式下可用
    } D_STATUS_SubCmd;
    typedef enum
    {
        D_FULL_ALARM = 0x0F5A, // 全量故障报警上报：0F5A。按位上报全量故障报警,数据信息：故障报警标志位信息(2nbytes)。查阅对应的故障报警标志位信息表,可以得到故障报警信息的详细解释
    } D_ALARM_STATUS_SubCmd;

    typedef enum
    {
        D_PARAM = 0x6C01,          // 上报状态变化的参数信息,数据信息：参数ID1 + 参数数据 + 参数ID2 + 参数数据 + ……
        D_USER_PARAM = 0x6D01,     // 上报全部用户数据信息
        D_EVENT_REPORT = 0x6E01,   // 上报事件信息及对应参数信息。数据信息：消息ID + 参数数据。见附录《事件数据表》。
        D_BigData_REPORT = 0x7D01, // 上报全部大数据信息.数据信息：大数据信息。见附录《大数据信息表》。
    } D_REPORT_SubCmd;
    typedef enum
    {
        D_SyncTime = 0x1000,     // 网络授时：0x1000，模块上电后，如果获取到网络时间，开始发送
        D_PID = 0x1001,          // 发送产品编码：0x1001，将产品编码发送给网络家电设备,数据信息：产品编码，26bytes，ASCII码，少于26bytes最右侧以0x00填充
        D_RegisterInfo = 0x2001, // 消息注册/注销结果：0x2001，将注册/注销结果发送给网络家电设备。数据信息：注册/注销结果(2bytes) + 消息注册/注销错误码(6bytes)
                                 // 注册/注销结果：0x00 00 注册成功；0x00 01 注册失败；0x00 02 注销成功；0x00 03 注销失败
        D_NotifyInfo = 0x2002,   // 消息告知：0x2002，告知网络家电设备有消息送达,数据信息：消息ID(8bytes) + 消息长度(2bytes)
        //...
    } D_SysDown_SubCmd;

    // typedef enum
    // {
    //     D_SyncTime = 0x1000,     // 网络授时：0x1000，模块上电后，如果获取到网络时间，开始发送
    //     D_PID = 0x1001,          // 发送产品编码：0x1001，将产品编码发送给网络家电设备,数据信息：产品编码，26bytes，ASCII码，少于26bytes最右侧以0x00填充
    //     D_RegisterInfo = 0x2001, // 消息注册/注销结果：0x2001，将注册/注销结果发送给网络家电设备。数据信息：注册/注销结果(2bytes) + 消息注册/注销错误码(6bytes)
    //                              // 注册/注销结果：0x00 00 注册成功；0x00 01 注册失败；0x00 02 注销成功；0x00 03 注销失败
    //     D_NotifyInfo = 0x2002,   // 消息告知：0x2002，告知网络家电设备有消息送达,数据信息：消息ID(8bytes) + 消息长度(2bytes)
    //     //...
    // } D_AskDeviceVer_SubCmd;

//-------------------------------------------------------
#define DeviceProtocolVer "E++2.19" // 设备协议版本 用ASCII码表示，区分大小写，不够8字节以0x00右侧填充。例：“E++2.19”
#define DeviceSoftVer "20240819"    // 默认为年月日共8个字节，用ASCII码表示，区分大小写。例：“20210521
#define UART_ENCRYPTION 0xF1        // 串口加密方式：0xF1 家电不支持加
#define DeviceReserve 0x0000        // 保留：默认0x00 00。
#define DeviceHardVer "20240819"    // 默认为年月日共8个字节，用ASCII码表示，区分大小写。例：“20210521
#define CommunicateType 0x00        // 0x00:交互模式，0x01：主从模式
#define SoftApName "U-BDSCAL"       // Soft-ap配置模式时的设备名称
#define DirectSlaverAddr 0x01       // 直连子机地址：与模块直接相连的子机的地址。不支持多子机，直连子机地址默认为0x01
#define NetModeAddr 0x00            // 模块地址总为0x00
#define HaierFleamHead 0xFFFF       // 串口包头
//-------------------------------------------------------
#define D_PAYLOAD_DATA_LEN_OFFSET2BUFF 13
#define D_PAYLOAD_DATA_LEN_FLEAM_LEN 8
//-------------------------------------------------------
#pragma pack(1)
    typedef struct
    {
        union
        {
            struct
            {
                unsigned char reserve01 : 2;  // 保留bit0，1
                unsigned char fleamEnd : 1;   // 分帧结尾
                unsigned char fleamStart : 1; // 分帧起始
                unsigned char reserve45 : 2;  // 保留bit4，5
                unsigned char CrcCheckEn : 1; // CRC校验
                unsigned char reserve7 : 1;   // 保留bit7
            } Bits;
            uint8_t Byte;
        } Flag;
        uint8_t reserveByte2; // 保留字节
        uint8_t fleamCnt;     // 分帧数
        uint8_t fleamFlagNum; // 响应回复信标
        uint8_t sourceAddr;   // 源地址
        uint8_t aimAddr;      // 目的地址
    } AddrSymbol_t;

    typedef struct
    {
        AddrSymbol_t addrSymbol;
        uint8_t fleamType;
    } payloadHead_t;

    typedef struct
    {
        uint8_t *payloadData;
        uint8_t sumCheck;
        uint16_t crcCheck;
        uint16_t fleamHead;
        uint8_t fleamLen;
        payloadHead_t payload;
    } fleamStruct_t;

    typedef struct
    {
        union
        {
            struct
            {
                unsigned char InTurn : 1;       // 是否支持交互模式
                unsigned char MasterSlaver : 1; // 是否支持主从模式
                unsigned char SupportCrc : 1;   // 是否支持CRC校验
                unsigned char MultiSlaver : 1;  // 是否支持多子机
            } Bits;
            uint16_t Byte;
        } Flag;
    } modeFunctionFlag_t;
    typedef struct
    {
        union
        {
            struct
            {
                unsigned char reserve01 : 2;    // 保留
                unsigned char SupportCrc : 1;   // 是否支持CRC校验
                unsigned char BaseBoardAsk : 1; // 是否支持底板信息查询
                unsigned char MultiSlaver : 1;  // 是否支持多子机
                unsigned char isDevice : 1;     // 是否支持设备角色
                unsigned char DeviceKey : 1;    // 是否支持设备Key
                unsigned char NewNetWork : 1;   // 是否支持新网络状态版本 此标志位为1，F1、F7按照新格式进行发送和解析。
                unsigned char MeshDevice : 1;   // 是否支持Mesh终端
                unsigned char PcBoard : 1;      // 是否支持电脑板功能
                unsigned char FlagAddr : 1;     // 是否支持信标和源目的地址
                unsigned char SplitFleam : 1;   // 是否支持信标和源目的地址
            } Bits;
            uint16_t Byte;
        } Flag;
    } DeviceFunctionFlag_t;

    typedef struct
    {
        union
        {
            struct
            {
                unsigned char commonDevice : 1; // 普通设备
                unsigned char gateWay : 1;      // 网关设备
                unsigned char attachment : 1;   // 附件设备
            } Bits;
            uint8_t Byte;
        } Flag;
    } RoleFlag_t;
#pragma pack()
    //-----------------------------------------------------
    void UartTransmitInit(void);
    extern fifo_data_t xUartFifoRx;
    extern StreamBufferDef xUartTxStreamBuffer;
    void HaiErUartDataDecode(fifo_data_t *sFifo);
    //-----------------------------------------------------
    void AckHaierDeviceVer(uint8_t fleamFlagNum);

#ifdef __cplusplus
}
#endif

#endif
